﻿/*
OpenShell: An open source library that implements the Powershell engine for console applications
Copyright (C) 2011 Bryan Perris

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation.Host;
using System.Text;

namespace OpenShell
{
    public sealed class ConsoleRawUserInterface : PSHostRawUserInterface
    {
        private ConsoleWindowHelper m_ConsoleHelper;

        public ConsoleRawUserInterface()
        {
            m_ConsoleHelper = new ConsoleWindowHelper();
        }
		
        public override ConsoleColor BackgroundColor
        {
            get { return Console.BackgroundColor; }
            set { Console.BackgroundColor = value; }
        }

        public override Size BufferSize
        {
            get { return new Size(Console.BufferWidth, Console.BufferHeight); }
            set { Console.SetBufferSize(value.Width, value.Height); }
        }

        public override Coordinates CursorPosition
        {
            get
            {
                return m_ConsoleHelper.GetCursorPositon();
            }
            set
            {
                m_ConsoleHelper.SetCursorPosition(value);
            }
        }

        public override int CursorSize
        {
            get { return Console.CursorSize; }
            set { Console.CursorSize = value; }
        }

        public override ConsoleColor ForegroundColor
        {
            get { return Console.ForegroundColor; }
            set { Console.ForegroundColor = value; }
        }

        public override bool KeyAvailable
        {
            get { return Console.KeyAvailable; }
        }

        public override Size MaxPhysicalWindowSize
        {
            get { return m_ConsoleHelper.GetMaxPhysicalWindowSize(); }
        }

        public override Size MaxWindowSize
        {
            get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); }
        }

        public override Coordinates WindowPosition
        {
            get { return new Coordinates(Console.WindowLeft, Console.WindowTop); }
            set { Console.SetWindowPosition(value.X, value.Y); }
        }

        public override Size WindowSize
        {
            get { return new Size(Console.WindowWidth, Console.WindowHeight); }
            set { Console.SetWindowSize(value.Width, value.Height); }
        }

        public override string WindowTitle
        {
            get { return Console.Title; }
            set { Console.Title = value; }
        }

        public override void FlushInputBuffer()
        {
            m_ConsoleHelper.FlushInputStream();
        }

        public override BufferCell[,] GetBufferContents(Rectangle rectangle)
        {
            return m_ConsoleHelper.GetBufferData(rectangle);
        }

        public override KeyInfo ReadKey(ReadKeyOptions options)
        {
            // Handle this method the best we can
            KeyInfo info = new KeyInfo();
            ConsoleKeyInfo cinfo = Console.ReadKey(true);

            info.Character = cinfo.KeyChar;

            switch (cinfo.Modifiers)
            {
                case ConsoleModifiers.Alt: info.ControlKeyState = ControlKeyStates.LeftAltPressed; break;
                case ConsoleModifiers.Control: info.ControlKeyState = ControlKeyStates.LeftCtrlPressed; break;
                case ConsoleModifiers.Shift: info.ControlKeyState = ControlKeyStates.ShiftPressed; break;
                default: info.ControlKeyState &= 0; break;
            }

            // Is this a safe way to do this?
            info.VirtualKeyCode = (int)cinfo.Key;

            return info;
        }

        public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill)
        {
            m_ConsoleHelper.ScrollScreenBuffer(source, destination, clip, fill);
        }

        public override void SetBufferContents(Coordinates origin, BufferCell[,] contents)
        {
            m_ConsoleHelper.SetBufferContents(origin, contents);
        }

        public override void SetBufferContents(Rectangle rectangle, BufferCell fill)
        {
            m_ConsoleHelper.FillBufferContents(rectangle, fill);
        }
    }
}
